#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using starLiGHT.ParticleSystem.Common;
using starLiGHT.ParticleSystem.twoD;
using starLiGHT.Render;
using starLiGHT.SceneManagement;
using starLiGHT.Input;
using System.Diagnostics;
using starLiGHT.Components.SandboxManager;
#endregion

namespace starLiGHT.Sandbox.Particles
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        InputManager inputManager;
        SpriteFont font;
        Stopwatch sw;
        ParticleSystemTest test;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            SandboxManager.SingleTest = null;
        }

        public Game1(String testName)
            : this()
        {
            if (String.IsNullOrEmpty(testName) || 
                testName.Equals("all", StringComparison.InvariantCultureIgnoreCase))
            {
                SandboxManager.SingleTest = null;
            }
            else
            {
                SandboxManager.SingleTest = testName;
            }
        }

        protected override void Initialize()
        {
            inputManager = new InputManager(this);
            this.Services.AddService(typeof(InputManager), inputManager);
            Components.Add(inputManager);

            InitializeInput();

            ParticleSystemManager.Instance._initialise();

            sw = new Stopwatch();

            base.Initialize();

            test = SandboxManager.getActTest(this) as ParticleSystemTest;
            test.Initialize(this, GraphicsDevice);
        
        }

        private void InitializeInput()
        {
            TriggerAction ta;

#if !WINDOWS_PHONE
            ta = inputManager.createAction("EXIT", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.Escape, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.Back, LogicalPlayerIndex.One));

            ta = inputManager.createAction("RESET", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.R, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.Start, LogicalPlayerIndex.One));

            ta = inputManager.createAction("NEXT_TEST", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.Add, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.RightShoulder, LogicalPlayerIndex.One));

            ta = inputManager.createAction("PREV_TEST", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.Subtract, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.LeftShoulder, LogicalPlayerIndex.One));
#endif
        }

        protected override void LoadContent()
        {

            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            font = Content.Load<SpriteFont>(@"Arial10");

            //Core.Instance.setRenderSystem(new starLiGHT.Render.TwoD.RenderSystemDefault());
            //Core.Instance.Initialize(GraphicsDevice, Content);
        }

        protected override void Update(GameTime gameTime)
        {
            if (inputManager.IsActionPress("EXIT")) this.Exit();

            if (inputManager.IsActionPress("RESET"))
            {
                test = SandboxManager.getActTest(this) as ParticleSystemTest;
                test.Initialize(this, GraphicsDevice);
            }

            if (inputManager.IsActionPress("NEXT_TEST"))
            {
                test = SandboxManager.getNextTest(this) as ParticleSystemTest;
                test.Initialize(this, GraphicsDevice);
            }

            if (inputManager.IsActionPress("PREV_TEST"))
            {
                test = SandboxManager.getPreviousTest(this) as ParticleSystemTest;
                test.Initialize(this, GraphicsDevice);
            }


            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            sw.Start();

            starLiGHT.ParticleSystem.Common.IRenderer renderer = test.ParticleSystem.getRenderer();
            if (renderer != null)
            {
                foreach (Emitter2D emitter in renderer.Emitters.Values)
                {
                    emitter.update((float)gameTime.ElapsedGameTime.TotalSeconds);
                    if (renderer.GetType() == typeof(RenderTargetRenderer))
                    {
                        ((RenderTargetRenderer)renderer).renderParticles(emitter.Particles.ToArray());
                    }
                    else if (renderer.GetType() == typeof(RenderTargetVectorLineRenderer))
                    {
                        ((RenderTargetVectorLineRenderer)renderer).renderParticles(emitter.Particles.ToArray());
                    }
                }
            }

            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);

            GraphicsDevice.RenderState.AlphaBlendEnable = true;
            GraphicsDevice.RenderState.SourceBlend = Blend.One;
            GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha; 

            if (renderer != null)
            {
                foreach (Emitter2D emitter in renderer.Emitters.Values)
                {
                    if (renderer.GetType() == typeof(RenderTargetRenderer))
                    {
                        spriteBatch.Draw(((RenderTargetRenderer)renderer).Texture, Vector2.Zero, Color.White);
                    }
                    else if (renderer.GetType() == typeof(RenderTargetVectorLineRenderer))
                    {
                        spriteBatch.Draw(((RenderTargetVectorLineRenderer)renderer).Texture, Vector2.Zero, Color.White);
                    }
                }
            }

            spriteBatch.End();

            sw.Stop();

            //
            // Draw debug data
            //
            spriteBatch.Begin();
            spriteBatch.DrawString(font, "Particle Demo: " +  test.Description, new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y), Color.White);
            spriteBatch.DrawString(font, "Time to render: " + sw.ElapsedMilliseconds.ToString() + "ms", new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y + font.LineSpacing), Color.White);
            spriteBatch.End();

            sw.Reset();
        }
    }
}
